package com.globallogic.javatrainings.sergiiivanov.tests;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Arrays;

import org.junit.Test;

import com.globallogic.javatrainings.sergiiivanov.model.MyArray;
import com.globallogic.javatrainings.sergiiivanov.model.Student;
import com.globallogic.javatrainings.sergiiivanov.model.UniversityFailure;
import com.globallogic.javatrainings.sergiiivanov.model.UniversityWarning;

public class MyArrayTest {

    @Test
    public void testAdd() throws UniversityFailure {
        MyArray<String> my = new MyArray<String>(new String[0]);
        String s = "";
        my.add(s);
        my.add(s);
        my.add(s);
        assertEquals(3, my.size());

        Integer i = new Integer(1);
        MyArray<Integer> my2 = new MyArray<Integer>(new Integer[0]);
        my2.add(i);
        my2.add(i);
        my2.add(i);
        assertEquals(3, my2.size());

        MyArray<String> s1 = new MyArray<String>();
        s1.add("test");
        assertEquals("test", s1.get(0));
    }

    @Test
    public void testDataMutations() throws UniversityFailure {
        Integer[] inp = { 1, 2 };
        MyArray<Integer> arr = new MyArray<Integer>(inp);
        inp[0] = 10;
        assertEquals(1, arr.get(0).intValue());
        int el = 3;
        arr.add(el);
        el = 30;
        assertEquals(3, arr.get(2).intValue());
        el = arr.get(0);
        el = 8;
        assertEquals(1, arr.get(0).intValue());
        Integer[] res = arr.toArray();
        res[0] = 100;
        assertEquals(1, arr.get(0).intValue());

        Integer[] unsorted = { 1, 3, 2 };
        MyArray<Integer> keepOrger = new MyArray<Integer>(unsorted);
        Integer[] sorted = keepOrger.toArray();
        Arrays.sort(sorted);
        assertArrayEquals(unsorted, keepOrger.toArray());
    }

    @Test
    public void testFind() {
        String[] strInp = { "A", "B", "C" };
        MyArray<String> a = new MyArray<String>(strInp);
        a.add("a");
        a.add("b");
        a.add("c");
        assertEquals(0, a.indexOf("A"));
        assertEquals(1, a.indexOf("B"));
        assertEquals(2, a.indexOf("C"));
        assertEquals(3, a.indexOf("a"));
        assertEquals(4, a.indexOf("b"));
        assertEquals(5, a.indexOf("c"));
    }

    @Test
    public void testGet() throws UniversityFailure {
        MyArray<String> a = new MyArray<String>(new String[0]);
        a.add("A");
        a.add("B");
        a.add("C");
        assertTrue(a.get(1).equals("B"));

        MyArray<Integer> b = new MyArray<Integer>(new Integer[0]);
        b.add(1);
        b.add(2);
        b.add(3);
        assertEquals(2, b.get(1).intValue());
    }

    @SuppressWarnings("unused")
    @Test
    public void testMyArray() throws UniversityFailure {
        try {
            MyArray<Integer> intArr1 = new MyArray<Integer>(new Integer[0]);
            assertTrue(true);
        } catch (Exception e) {
            fail("Integer not supported: " + e.getMessage());
        }
        try {
            MyArray<String> strArr1 = new MyArray<String>(new String[0]);
            assertTrue(true);
        } catch (Exception e) {
            fail("String not supported: " + e.getMessage());
        }
    }

    @SuppressWarnings("unused")
    @Test
    public void testMyArrayTArray() {
        try {
            Integer[] intInp = { 1, 2, 3 };
            MyArray<Integer> intArr2 = new MyArray<Integer>(intInp);
            assertTrue(true);
        } catch (Exception e) {
            fail("Integer is not supported: " + e.getMessage());
        }
        try {
            String[] strInp = { "A", "B", "C" };
            MyArray<String> strArr2 = new MyArray<String>(strInp);
            assertTrue(true);
        } catch (Exception e) {
            fail("String is not supported: " + e.getMessage());
        }
    }

    @Test
    public void testRemove() throws UniversityFailure {
        MyArray<Integer> my;
        my = new MyArray<Integer>(new Integer[0]);
        for (int i = 0; i <= 6; i++) {
            my.add(i);
        }
        assertEquals(7, my.size());
        my.remove(0);
        assertEquals(6, my.size());
        assertEquals(1, my.get(0).intValue());
        assertEquals(6, my.get(5).intValue());
        try {
            assertNull(my.get(6));
            fail("illegal data transformation");
        } catch (Exception e) {
            assertEquals(new UniversityFailure().getClass(), e.getClass());
        }

        my = new MyArray<Integer>(new Integer[0]);
        for (int i = 0; i <= 6; i++) {
            my.add(i);
        }
        my.remove(6);
        assertEquals(6, my.size());
        assertEquals(0, my.get(0).intValue());
        assertEquals(5, my.get(5).intValue());

        my = new MyArray<Integer>(new Integer[0]);
        for (int i = 0; i <= 6; i++) {
            my.add(i);
        }
        my.remove(1);
        assertEquals(6, my.size());
        assertEquals(0, my.get(0).intValue());
        assertEquals(6, my.get(5).intValue());

        my = new MyArray<Integer>(new Integer[0]);
        for (int i = 0; i <= 6; i++) {
            my.add(i);
        }
        my.remove(3);
        assertEquals(6, my.size());
        assertEquals(0, my.get(0).intValue());
        assertEquals(6, my.get(5).intValue());
    }

    @Test
    public void testRemoveInt() throws UniversityFailure {
        String[] strInp = { "A", "B", "C" };
        MyArray<String> a = new MyArray<String>(strInp);
        a.remove(1);
        assertEquals(2, a.size());
        String[] expected = { "A", "C" };
        assertArrayEquals(expected, a.toArray());
    }

    @Test
    public void testRemoveObject() {
        String[] strInp = { "A", "B", "C" };
        MyArray<String> a = new MyArray<String>(strInp);
        a.remove("B");
        assertEquals(2, a.size());
        String[] expected = { "A", "C" };
        assertArrayEquals(expected, a.toArray());

    }

    @Test
    public void testSet() throws UniversityFailure {
        Integer[] boo = { 1, 2, 3 };
        MyArray<Integer> b = new MyArray<Integer>(boo);
        b.set(1, 9);
        assertEquals(9, b.get(1).intValue());
        assertEquals(2, boo[1].intValue());
    }

    @Test
    public void testSize() throws UniversityFailure {
        testAdd();
    }

    @Test
    public void testToArray() {
        String[] strInp = { "A", "B", "C" };
        MyArray<String> a = new MyArray<String>(strInp);
        assertArrayEquals("String array", strInp, a.toArray());
        a.add("d");
        String[] strEq = { "A", "B", "C", "d" };
        assertArrayEquals("String array", strEq, a.toArray());
        String[] res = a.toArray();
        assertArrayEquals("String array", strEq, res);

        MyArray<String> a2 = new MyArray<String>(new String[0]);
        a2.add("A");
        a2.add("B");
        a2.add("C");
        String[] r = a2.toArray();
        assertArrayEquals("String array", strInp, r);

        Integer[] intInp = { 1, 2, 3 };
        MyArray<Integer> b = new MyArray<Integer>(intInp);
        assertArrayEquals("Integer array", intInp, b.toArray());
    }

    @Test
    public void testWipeData() {
        MyArray<String> a2 = new MyArray<String>(new String[0]);
        a2.add("A");
        a2.add("B");
        a2.add("C");
        a2.clear();
        assertEquals(0, a2.size());
    }

    @SuppressWarnings("unused")
    @Test
    public void testIterator() {
        MyArray<String> sArr = new MyArray<String>();
        for (String s : sArr) {
            fail("MyArray iterator entered into empty loop");
        }
        sArr.add("1");
        sArr.add("2");
        sArr.add("3");
        sArr.add("4");
        sArr.add("5");
        String boo = "fail";
        for (String s : sArr) {
            boo = s;
        }
        assertEquals("5", boo);
        sArr.clear();
        for (String s : sArr) {
            fail("MyArray iterator entered into empty loop after clear()");
        }
        sArr.add(null);
        sArr.add(null);
        for (String s : sArr) {
            boo = s;
            assertNull(s, boo);
        }

    }

    @Test
    public void testMyArrayToNamesCovertable() throws UniversityFailure, UniversityWarning {
        MyArray<Student> s = new MyArray<Student>(new Student[] { new Student(), new Student() });
        assertArrayEquals(new String[] { null, null }, s.toNamesList());
        MyArray<Student> s2 = new MyArray<Student>(new Student[] { new Student("b", "z", "x"), new Student("c", "z", "x") });
        assertArrayEquals(new String[] { "b", "c" }, s2.toNamesList());
        String[] n = s2.toNamesList();
        n[1] = "c";
        assertArrayEquals(new String[] { "b", "c" }, s2.toNamesList());
    }

    @Test
    public void testCopy() throws UniversityFailure, UniversityWarning {
        Student a = new Student("b", "z", "x");
        Student b = new Student("c", "z", "x");
        MyArray<Student> s = new MyArray<Student>(new Student[] { a, b });
        assertEquals(2, s.size());
        MyArray<Student> s2 = s.copy();
        s2.add(new Student());
        assertEquals(2, s.size());
        assertEquals(3, s2.size());
        assertEquals(a, s.get(0));
        assertEquals(a, s2.get(0));
    }
}
